import os
import time
import traceback
import tinify
import uuid
from PIL import Image
from flask import Blueprint, request, jsonify, send_from_directory
from werkzeug.exceptions import RequestEntityTooLarge

from config.settings import (
    UPLOAD_FOLDER, COMPRESSED_FOLDER, MAX_FILE_SIZE, 
    MAX_FILES_COUNT, TINIFY_API_KEY
)
from utils.logger import logger
from utils.file_utils import (
    allowed_file, secure_filename_with_chinese, 
    generate_unique_filename
)

# 创建蓝图
compress_bp = Blueprint('compress', __name__)

@compress_bp.route('/api/compress', methods=['POST'])
def compress_images():
    """
    处理图片压缩请求
    """
    start_time = time.time()
    logger.info("收到压缩请求")
    
    try:
        # 检查是否有文件被上传
        if 'files[]' not in request.files:
            logger.warning("请求中没有文件部分")
            return jsonify({'error': '请求中没有文件部分'}), 400
        
        files = request.files.getlist('files[]')
        compression_method = request.form.get('method', 'tinypng')  # 默认使用TinyPNG
        logger.info(f"压缩方法: {compression_method}, 文件数量: {len(files)}")
        
        if not files or files[0].filename == '':
            logger.warning("没有选择文件")
            return jsonify({'error': '没有选择文件'}), 400
            
        # 检查文件数量限制
        if len(files) > MAX_FILES_COUNT:
            logger.warning(f"文件数量超过限制: {len(files)} > {MAX_FILES_COUNT}")
            return jsonify({'error': f'单次最多上传 {MAX_FILES_COUNT} 个文件，当前选择了 {len(files)} 个'}), 400
        
        results = []
    
        for file in files:
            file_start_time = time.time()
            logger.info(f"开始处理文件: {file.filename}")
            
            # 检查单个文件大小
            file.seek(0, os.SEEK_END)
            file_size = file.tell()
            file.seek(0)  # 重置文件指针
            
            if file_size > MAX_FILE_SIZE:
                logger.warning(f"文件大小超过限制: {file.filename}, {file_size / (1024 * 1024):.2f}MB > {MAX_FILE_SIZE / (1024 * 1024):.1f}MB")
                results.append({
                    'filename': file.filename,
                    'error': f'文件大小超过限制 ({MAX_FILE_SIZE / (1024 * 1024):.1f}MB)'
                })
                continue
                
            if file and allowed_file(file.filename):
                # 安全地获取文件名并生成唯一文件名
                original_filename = file.filename
                filename = secure_filename_with_chinese(original_filename)
                
                # 确保文件扩展名正确
                if '.' not in filename:
                    ext = ''
                    for allowed_ext in ALLOWED_EXTENSIONS:
                        if original_filename.lower().endswith(f'.{allowed_ext}'):
                            ext = allowed_ext
                            break
                    if ext:
                        filename = f"{filename}.{ext}"
                    else:
                        logger.warning(f"无法确定文件扩展名: {original_filename}")
                        results.append({
                            'filename': original_filename,
                            'error': '无法确定文件扩展名'
                        })
                        continue
                unique_filename = generate_unique_filename(filename)
                upload_path = os.path.join(UPLOAD_FOLDER, unique_filename)
                compressed_path = os.path.join(COMPRESSED_FOLDER, unique_filename)
                
                logger.info(f"处理文件: {filename}")
                
                try:
                    # 保存上传的文件
                    file.save(upload_path)
                    logger.debug(f"文件已保存到: {upload_path}")
                    
                    original_size = os.path.getsize(upload_path)
                    logger.info(f"原始文件大小: {original_size / 1024:.2f} KB")
                    
                    # 根据选择的方法进行压缩
                    if compression_method == 'tinypng' and TINIFY_API_KEY:
                        logger.info(f"使用TinyPNG API压缩: {filename}")
                        # 使用TinyPNG API进行压缩
                        tinify.key = TINIFY_API_KEY
                        source = tinify.from_file(upload_path)
                        source.to_file(compressed_path)
                    else:
                        logger.info(f"使用PIL本地压缩: {filename}")
                        # 使用PIL进行基本压缩（作为备选方案）
                        img = Image.open(upload_path)
                        
                        # 转换为RGB模式（如果是RGBA）
                        if img.mode == 'RGBA':
                            logger.debug(f"将RGBA图像转换为RGB: {filename}")
                            img = img.convert('RGB')
                        
                        # 使用PIL进行压缩
                        img.save(compressed_path, optimize=True, quality=85)
                    
                    compressed_size = os.path.getsize(compressed_path)
                    logger.info(f"压缩后文件大小: {compressed_size / 1024:.2f} KB")
                    
                    # 计算压缩率
                    compression_rate = ((original_size - compressed_size) / original_size) * 100
                    logger.info(f"压缩率: {compression_rate:.2f}%")
                    
                    file_process_time = time.time() - file_start_time
                    logger.info(f"文件处理完成: {filename}, 耗时: {file_process_time:.2f}秒")
                    
                    results.append({
                        'filename': filename,
                        'original_size': original_size,
                        'compressed_size': compressed_size,
                        'compression_rate': round(compression_rate, 2),
                        'url': f'/api/files/compressed/{unique_filename}'
                    })
                except Exception as e:
                    # 如果压缩失败，记录错误并返回错误信息
                    error_msg = str(e)
                    logger.error(f"处理文件 {filename} 时出错: {error_msg}")
                    logger.error(traceback.format_exc())
                    
                    results.append({
                        'filename': filename,
                        'error': error_msg
                    })
                    # 删除上传的文件
                    if os.path.exists(upload_path):
                        logger.debug(f"删除上传的文件: {upload_path}")
                        os.remove(upload_path)
                    continue
            else:
                logger.warning(f"不支持的文件类型: {file.filename}")
                results.append({
                    'filename': file.filename,
                    'error': '不支持的文件类型'
                })
    
        total_time = time.time() - start_time
        logger.info(f"压缩请求处理完成, 总耗时: {total_time:.2f}秒, 处理文件数: {len(results)}")
        return jsonify({'results': results})
    except RequestEntityTooLarge:
        logger.error("请求实体过大")
        return jsonify({'error': f'文件大小超过限制 (每个文件最大 {MAX_FILE_SIZE / (1024 * 1024):.1f}MB，最多 {MAX_FILES_COUNT} 个文件)'}), 413
    except Exception as e:
        logger.error(f"处理压缩请求时出错: {str(e)}")
        logger.error(traceback.format_exc())
        return jsonify({'error': '服务器内部错误'}), 500

@compress_bp.route('/api/files/compressed/<filename>', methods=['GET'])
def get_compressed_file(filename):
    """
    获取压缩后的文件
    """
    logger.info(f"请求下载压缩文件: {filename}")
    try:
        return send_from_directory(COMPRESSED_FOLDER, filename)
    except Exception as e:
        logger.error(f"下载文件 {filename} 时出错: {str(e)}")
        logger.error(traceback.format_exc())
        return jsonify({'error': '文件不存在或无法访问'}), 404